﻿using GenericDataSourceControl;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
using System.Data.Linq;

namespace GenericDataSourceControl.Tests
{
    
    
    /// <summary>
    ///This is a test class for ExtensionsTest and is intended
    ///to contain all ExtensionsTest Unit Tests
    ///</summary>
    [TestClass()]
    public class ExtensionsTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for Page
        ///</summary>
        [TestMethod()]
        public void PageTest()
        {
            IQueryable<string> query = new List<string>()
            {
                "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"
            }.AsQueryable<string>();

            int startRowIndex = 2;
            int maximumRows = 4;
            IQueryable<string> expected = new List<string>()
            {
                "Two", "Three", "Four", "Five",
            }.AsQueryable<string>();

            IQueryable<string> actual;
            actual = GenericUtility.Page(query, startRowIndex, maximumRows) as IQueryable<string>;
            
            var except = actual.Except(expected);
            Assert.AreEqual(0, except.Count());

            except = expected.Except(actual);
            Assert.AreEqual(0, except.Count());
        }

        /// <summary>
        ///A test for Sort
        ///</summary>
        [TestMethod()]
        public void SortTest()
        {
            List<SampleItem> query = new List<SampleItem>()
            {
               new SampleItem()
               {
                   Name = "One",
                   Value = 1,
               },
               new SampleItem()
               {
                   Name = "Two",
                   Value = 2,
               },
               new SampleItem()
               {
                   Name = "Three",
                   Value = 3,
               },
               new SampleItem()
               {
                   Name = "Four",
                   Value = 4,
               },
               new SampleItem()
               {
                   Name = "Five",
                   Value = 5,
               },
               new SampleItem()
               {
                   Name = "Six",
                   Value = 6,
               },
               new SampleItem()
               {
                   Name = "Seven",
                   Value = 7,
               },
               new SampleItem()
               {
                   Name = "Eight",
                   Value = 8,
               },
               new SampleItem()
               {
                   Name = "Nine",
                   Value = 9,
               },
            };

            string sortExpression = "Name DESC";
            var actual =  GenericUtility.Sort(query.AsQueryable(), sortExpression).OfType<SampleItem>();

            var expected = query.OrderByDescending(p => p.Name);

            for (int i = 0; i < actual.Count(); i++)
            {
                Assert.AreEqual(expected.ElementAt(i), actual.ElementAt(i));
            }
        }

        /// <summary>
        ///A test for ConvertValue
        ///</summary>
        [TestMethod()]
        public void ConvertValueTest()
        {
            //Testing String >> int
            object value = "123";
            object expected = 123;
            object actual;
            actual = GenericUtility.ConvertTo(value, typeof(int));
            Assert.AreEqual(expected, actual);

            //testing String >> Nullable<int>
            value = "123";
            expected = (int?)123;
            actual = GenericUtility.ConvertTo(value, typeof(int?));
            Assert.AreEqual(expected, actual);

            //testing String >> Nullable<int>
            value = "";
            expected = null;
            actual = GenericUtility.ConvertTo(value, typeof(int?));
            Assert.AreEqual(expected, actual);

            //testing String >> Enum
            value = SampleEnum.One.ToString();
            expected = SampleEnum.One;
            actual = GenericUtility.ConvertTo(value, typeof(SampleEnum));
            Assert.AreEqual(expected, actual);

            //testing string >> Nullable<enum>
            value = default(string);
            expected = null;
            actual = GenericUtility.ConvertTo(value, typeof(SampleEnum?));
            Assert.AreEqual(expected, actual);

            //Testing String (numerical value) >> Enum
            value = ((int)SampleEnum.One).ToString();
            expected = SampleEnum.One;
            actual = GenericUtility.ConvertTo(value, typeof(SampleEnum));
            Assert.AreEqual(expected, actual);

            //Testing String >> Guid
            value = Guid.NewGuid().ToString();
            expected = new Guid(value.ToString());
            actual = GenericUtility.ConvertTo(value, typeof(Guid?));
            Assert.AreEqual(expected, actual);
            
            //Testing String >> Data.Linq.Binary
            value = new byte[100];
            expected = new Binary((byte[])value);
            actual = GenericUtility.ConvertTo(value, typeof(Binary));
            Assert.AreEqual(expected, actual);

            //Testing TimeSpan
            value = TimeSpan.FromMinutes(123).ToString();
            expected = TimeSpan.FromMinutes(123);
            actual = GenericUtility.ConvertTo<TimeSpan>(value);
            Assert.AreEqual(expected, actual);

        }

        [TestMethod]
        public void TestBuilObjectWithMembers()
        {
            var actual = new TestItem();

            var values = new Dictionary<string, object>();
            string name = "Vasile";
            int age = 21;
            string address = "AAA";
            values.Add("Name", name);
            values.Add("Age", 21);
            values.Add("Address", address);

            values.BuildObject<TestItem>(actual);

            Assert.AreEqual(address, actual.Address);
            Assert.AreEqual(name, actual.Name);
            Assert.AreEqual(age, actual.Age);
        }

        protected class TestItem
        {
            public string Name;
            public int Age;
            public string Address { get; set; }
        }
    }
}
